不是,栈区是进程的一部分,而程序不是进程。(什么咬文嚼字233)
概念:进程是正在运行的程序。包括程序计数器,栈区和数据区。
系统初始化,用户请求,系统调用,批处理初始化。
我觉得括号里面说的很明白了2333
用 UNIX 系统举例 (详情见书 P88 最后一段)
fork
/exec
系统调用生成子进程execvp
系统调用,使用执行程序的程序段和代码段覆盖。概念:进程的状态有准备态(Ready),等待态(Waiting),运行态(Running)
先告诉你有四个。
int main(){
pid_t pid;
for (int i = 0; i < 2; i++)
pid = fork();
}
移除所有队列,释放占用的系统资源(内存等),然后返回操作系统。有可能出现僵尸进程,得让父进程来终结:-P
进程终结状态如下:
PCB (Process Control Block):进程控制块。重点包括以下东西:
注意:第六条直译为会计信息。我有两个理解:进程状态信息 / 用户信息 (我的上帝啊,谁能给我本翻译得十分不错的 Modern Operating System 啊)
对于操作系统来说,中断或者切换一个进程的代价太高了。
操作系统收到一个信息后,创建一个线程来处理信息。
概念:进程分为用户态线程(管理归进程),系统态线程(管理归操作系统),混合态进程,以及弹出态进程
By Multilevel Quene Fixed Priority scheduling algorithm, there are 3 priority quenes and 7 processes with following information. Draw the CPU scheduling Gantt chart and complete the following table for the give processes information.
通过多层级队列混合优先级 (Multilevel Quene Fixed Priorty) 调度算法,总共有三个优先级队列和七个进程,信息如下。画出 CPU 调度甘特图,然后根据信息填写最下面的表格。
enter_region:
MOVE REGISTER,___(1)___;
XCHG REGISTER,LOCK;
CMP REGISTER,#1;
JE OK;
CALL ___(2)___;
JMP ___(3)___;
ok: RET;
leave_region:
MOVE LOCK,___(4)___;
RET;
根据 CMP REGISTER,#1; JE OK; ok: RET;
可分析出 #1
是没上锁,#0
是上锁了。XCHG
可以互换两个寄存器的值,如果第一个空填入的是 #1
,那么无论如何,判断都是没上锁。所以第一个空填入 #0
。
第二个和第三个空是忙等待的东西,分别填的是 thread_yield
(找另外一个进程)和 enter_region
。
第四个空填入
#1
,用完了就解锁。
概念 互斥访问策略
TSL
指令。请修改附件中的代码,实现strict alternation机制(注要能够运行)。此外需要说明程序中那个部分是关键区,以及它为什么是关键区。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // For sleep().
// Critical region, because both threads needs to access this.
int a;
// Lock Variable
int turn = 0;
// Thread 2.
void * th(void *p)
{
while(1)
{
while(turn!=1) /*loop*/;
sleep(1);a=0; // Access Critical Region
printf("a=%d haha\n",a);// Stop access.
turn=0; // Change mark.
}
}
int main()
{
a=0;
pthread_t myth;
pthread_create(&myth,NULL,th,NULL);
// Thread 1.
while(1)
{
while(turn!=0) /*loop*/;
sleep(1);a=1; // Access Critical Region.
printf("a=%d hehe\n",a);// Stop access.
turn=1; // Change mark.
}
}
以下是编译运行方式。
gcc thread.c -lpthread -o thread && ./thread
ps -aux | grep thread # 记下 pid 号码
top -H -p PID # 查看该 PID 对应的线程状态
本程序的关键区是 a
和 turn
,因为它是两个进程共享的数据区域。其中 a
是两个进程互相访问的数据区,turn 是锁变量。
阅读代码,看看有啥问题。
在单核 CPU 上:
先执行消费者进程:
发现仓库里没有东西,准备睡眠。但是还没睡眠,进程切换到生产者了。
生产者开始生产产品,发现仓库里有东西,向消费者进程发出唤醒信号。进程切换到消费者。
消费者进程是醒着的,只是准备睡眠,把唤醒信号忽略掉,然后睡眠了,退出了
CPU 。
最后生产者把仓库填满了,也睡了。两个进程都睡了:-P
如果目前仓库满了:
生产者决定睡眠,但还没睡,进程切换到消费者了。
消费者用了一个产品,发现仓库里数量为
N-1,唤醒生产者。
生产者忽略了唤醒信号,睡眠。
消费者用完了所有东西,也睡了:-P
要点:准备睡眠时切换进程了,唤醒信号被忽略。
Mutex 实现在用户态,代价低,数量上限高。Semaphore 实现在内核态,代价高,数量上限低。
SuperBart 2022-04-09